home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / editors / mjovesrc.zoo / iproc-pt.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  9KB  |  439 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. /* NOTE WELL:
  9.  * This file is "included" into iproc.c -- it is not compiled separately!
  10.  */
  11.  
  12. #ifdef MiNT
  13. #include <mintbind.h>
  14. #endif
  15. #include <sys/time.h>
  16. #include <fcntl.h>
  17. #include <signal.h>
  18. #include <sgtty.h>
  19. #include "wait.h"
  20.  
  21. #define DEAD    1    /* dead but haven't informed user yet */
  22. #define STOPPED    2    /* job stopped */
  23. #define RUNNING    3    /* just running */
  24. #define NEW    4    /* brand new, never been ... received no input */
  25.  
  26. /* If process is dead, flags says how. */
  27. #define EXITED    1
  28. #define KILLED    2
  29.  
  30. #define isdead(p)    ((p) == NULL || proc_state((p)) == DEAD || (p)->p_fd == -1)
  31. #define makedead(p)    { proc_state((p)) = DEAD; }
  32.  
  33. #define proc_buf(p)    ((p)->p_buffer->b_name)
  34. #define proc_cmd(p)    ((p)->p_name)
  35. #define proc_state(p)    ((p)->p_state)
  36.  
  37. private Process    *procs = NULL;
  38.  
  39. long    global_fd = 1;
  40. int    NumProcs = 0;
  41.  
  42. #include "ttystate.h"
  43.  
  44. private Process *
  45. proc_pid(pid)
  46. int    pid;
  47. {
  48.     register Process    *p;
  49.  
  50.     for (p = procs; p != NULL; p = p->p_next)
  51.         if (p->p_pid == pid)
  52.             break;
  53.  
  54.     return p;
  55. }
  56.  
  57. void
  58. read_proc(fd)
  59. register int    fd;
  60. {
  61.     register Process    *p;
  62.     int    n;
  63.     char    ibuf[1024];
  64.  
  65.     for (p = procs; p != NULL; p = p->p_next)
  66.         if (p->p_fd == fd)
  67.             break;
  68.  
  69.     if (p == NULL) {
  70.         writef("\riproc: unknown fd %d", fd);
  71.         return;
  72.     }
  73.  
  74.     n = read(fd, (UnivPtr) ibuf, sizeof(ibuf) - 1);
  75. #ifdef MiNT
  76. /* XXX-> don't have either EIO or EWOULDBLOCK */
  77.     if (n <= 0) {
  78. #else
  79.     if (n == -1 && (errno == EIO || errno == EWOULDBLOCK)) {
  80. #endif /* MiNT */
  81.         if (proc_state(p) == NEW)
  82.             return;
  83.         proc_close(p);
  84.         makedead(p);
  85.         return;
  86.     } else {
  87.         if (proc_state(p) != RUNNING) {
  88.             proc_state(p) = RUNNING;
  89.             UpdModLine = YES;
  90.         }
  91.     }
  92.     if (n <= 0) {
  93.         if (n == 0)
  94.             strcpy(ibuf, "[Process EOF]");
  95.         else
  96.             swritef(ibuf, sizeof(ibuf),
  97.                 "\n[pty read error: %d]\n", errno);
  98.     } else
  99.         ibuf[n] = '\0';
  100.     proc_rec(p, ibuf);
  101. }
  102.  
  103. void
  104. ProcKill()
  105. {
  106.     register Buffer    *b;
  107.     char    *bname;
  108.  
  109.     bname = ask_buf(curbuf);
  110.  
  111.     if ((b = buf_exists(bname)) == NULL)
  112.         complain("[No such buffer]");
  113.     if (b->b_process == NULL)
  114.         complain("%s not tied to a process.", bname);
  115.     proc_kill(b->b_process, SIGKILL);
  116. }
  117.  
  118. void
  119. ProcCont()
  120. {
  121.     Process    *p;
  122.  
  123.     if ((p = curbuf->b_process) == NULL)
  124.         complain("[No process]");
  125.     if (p->p_state != DEAD) {
  126.         proc_kill(p, SIGCONT);
  127.         UpdModLine = YES;
  128.         p->p_state = RUNNING;
  129.     }
  130. }
  131.  
  132. private void
  133. send_p(c)
  134. char    c;
  135. {
  136.     Process    *p;
  137.     char    buf[2];
  138.  
  139.     if ((p = curbuf->b_process) == NULL)
  140.         complain("[No process]");
  141.     ToLast();
  142.     buf[0] = c;
  143.     buf[1] = '\0';
  144.     proc_rec(p, buf);
  145.     (void) write(p->p_fd, (UnivPtr) &c, (size_t) 1);
  146. }
  147.  
  148. void
  149. ProcEof()
  150. {
  151.     send_p(tc[OFF].t_eofc);
  152. }
  153.  
  154. void
  155. ProcInt()
  156. {
  157.     send_p(tc[OFF].t_intrc);
  158. }
  159.  
  160. void
  161. ProcQuit()
  162. {
  163.     send_p(tc[OFF].t_quitc);
  164. }
  165.  
  166. void
  167. ProcStop()
  168. {
  169.     send_p(ls[OFF].t_suspc);
  170. }
  171.  
  172. void
  173. ProcDStop()
  174. {
  175.     send_p(ls[OFF].t_dsuspc);
  176. }
  177.  
  178. private void
  179. proc_close(p)
  180. Process *p;
  181. {
  182.     SigHold(SIGCHLD);    /* be mutually exclusive */
  183.  
  184.     if (p->p_fd >= 0) {
  185.         (void) close(p->p_fd);
  186.         global_fd &= ~(1L << p->p_fd);
  187.         NumProcs -= 1;
  188. #ifdef MiNT
  189.         p->p_fd = -10;   /* MiNT 0.91 has already used negative
  190.                     file handles up to -5, so hopefully
  191.                     this should work for a little while
  192.                     at least ;-) */
  193. #else
  194.         p->p_fd = -1;
  195. #endif /* MiNT */
  196.     }
  197.  
  198.     SigRelse(SIGCHLD);
  199. }
  200.  
  201. private void
  202. proc_write(p, buf, nbytes)
  203. Process *p;
  204. char    *buf;
  205. size_t    nbytes;
  206. {
  207.     long    mask = (1 << p->p_fd);
  208.  
  209.     while (write(p->p_fd, (UnivPtr) buf, nbytes) <  0)
  210.         select(p->p_fd + 1, (long *)NULL, &mask, (long *)NULL, (struct timeval *)NULL);
  211. }
  212.  
  213. #ifdef    STDARGS
  214.     private void
  215. proc_strt(char *bufname, int clobber, ...)
  216. #else
  217.     private /*VARARGS2*/ void
  218. proc_strt(bufname, clobber, va_alist)
  219.     char    *bufname;
  220.     int    clobber;
  221.     va_dcl
  222. #endif
  223. {
  224.     va_list    ap;
  225.     char    *argv[32],
  226.         *cp;
  227.     Window *owind = curwind;
  228.     int    pid;
  229.     Process    *newp;
  230.     Buffer     *newbuf;
  231.     int    i,
  232.         ptyfd = -1,
  233.         ttyfd,
  234.         ldisc,
  235.         lmode;
  236.     register char    *s,
  237.             *t;
  238.     char    ttybuf[15],
  239.         ptybuf[15];
  240.     char    cmdbuf[LBSIZE];
  241. #ifdef    BRLUNIX
  242.     struct sg_brl sgt;
  243. #else
  244.     struct sgttyb sgt;
  245. #endif
  246.  
  247. #ifdef    TIOCGWINSZ
  248.     struct winsize win;
  249. #else
  250. #  ifdef    BTL_BLIT
  251. #  include <sys/jioctl.h>
  252.     struct jwinsize jwin;
  253. #  endif
  254. #endif
  255.  
  256.     isprocbuf(bufname);    /* make sure BUFNAME is either nonexistant
  257.                    or is of type B_PROCESS */
  258.     va_init(ap, clobber);
  259.     make_argv(argv, ap);
  260.     va_end(ap);
  261.     if (access(argv[0], X_OK) != 0) {
  262.         complain("[Couldn't access %s: %s]", argv[0], strerror(errno));
  263.         /* NOTREACHED */
  264.     }
  265.     for (s = "pqrs"; ptyfd<0; s++) {
  266.         if (*s == '\0')
  267.             complain("[Out of ptys!]");
  268.         for (t = "0123456789abcdef"; *t; t++) {
  269. #ifdef MiNT
  270.             swritef(ptybuf, sizeof(ptybuf), "U:\\pipe\\jove%c%c",*s, *t);
  271. #else
  272.             swritef(ptybuf, sizeof(ptybuf), "/dev/pty%c%c", *s, *t);
  273. #endif
  274. #ifdef MiNT
  275.             if ((ptyfd=Fcreate(ptybuf,FA_SYSTEM|FA_HIDDEN)) >= 0) {
  276. #else
  277.             if ((ptyfd = open(ptybuf, 2)) >= 0) {
  278. #endif
  279.                 strcpy(ttybuf, ptybuf);
  280. #ifndef MiNT
  281.                 ttybuf[5] = 't';
  282. #endif
  283.                 /* make sure both ends are available */
  284.                 if ((i = open(ttybuf, 2)) < 0) {
  285.                     (void) close(ptyfd);
  286.                     ptyfd = -1;
  287.                 } else {
  288.                     (void) close(i);
  289.                     break;
  290.                 }
  291.             }
  292.         }
  293.     }
  294.  
  295. #ifdef    TIOCGETD
  296.     (void) ioctl(0, TIOCGETD, (UnivPtr) &ldisc);
  297. #endif
  298. #ifdef    TIOCLGET
  299.     (void) ioctl(0, TIOCLGET, (UnivPtr) &lmode);
  300. #endif
  301. #ifdef    TIOCGWINSZ
  302.     (void) ioctl(0, TIOCGWINSZ, (UnivPtr) &win);
  303. #else
  304. #  ifdef    BTL_BLIT
  305.     (void) ioctl(0, JWINSIZE, (UnivPtr) &jwin);
  306. #  endif    /* BTL_BLIT */
  307. #endif
  308.  
  309.     SigHold(SIGCHLD);
  310. #ifdef    SIGWINCH
  311.     SigHold(SIGWINCH);
  312. #endif
  313.     switch (pid = fork()) {
  314.     case -1:
  315.         (void) close(ptyfd);
  316.         message("[Fork failed!]");
  317.         goto fail;
  318.  
  319.     case 0:
  320.         SigRelse(SIGCHLD);
  321. #ifdef    SIGWINCH
  322.         SigRelse(SIGWINCH);
  323. #endif
  324.         for (i = 0; i < 32; i++)
  325.             (void) close(i);
  326.  
  327. #ifdef    TIOCNOTTY
  328.         if ((i = open("U:\\dev\\tty", 2)) >= 0) {
  329.             (void) ioctl(i, TIOCNOTTY, (UnivPtr)NULL);
  330.             (void) close(i);
  331.         }
  332. #endif
  333.         if ((ttyfd = open(ttybuf, 2)) < 0)
  334.             exit(-1);
  335. #ifdef MiNT
  336.         (void) dup2(ttyfd, -1);
  337.         (void) dup2(ttyfd, 0);
  338. #endif /* MiNT */
  339.         (void) dup2(ttyfd, 1);
  340.         (void) dup2(ttyfd, 2);
  341.  
  342. #ifdef    TIOCSETD
  343.         (void) ioctl(0, TIOCSETD, (UnivPtr) &ldisc);
  344. #endif
  345. #ifdef    TIOCLSET
  346.         (void) ioctl(0, TIOCLSET, (UnivPtr) &lmode);
  347. #endif
  348. #ifdef    TIOCSETC
  349.         (void) ioctl(0, TIOCSETC, (UnivPtr) &tc[OFF]);
  350. #endif
  351. #ifdef    TIOCSLTC
  352.         (void) ioctl(0, TIOCSLTC, (UnivPtr) &ls[OFF]);
  353. #endif
  354.  
  355. #ifdef    TIOCGWINSZ
  356. #    ifdef    SIGWINCH
  357.         (void) signal(SIGWINCH, SIG_IGN);
  358. #    endif
  359.         win.ws_row = curwind->w_height;
  360.         (void) ioctl(0, TIOCSWINSZ, (UnivPtr) &win);
  361. #else
  362. #  ifdef    BTL_BLIT
  363.         jwin.bytesy = curwind->w_height;
  364.         (void) ioctl(0, JSWINSIZE, (UnivPtr) &jwin);
  365. #  endif
  366. #endif
  367.  
  368.         sgt = sg[OFF];
  369.         sgt.sg_flags &= ~(ECHO | CRMOD /* | ANYP  | ALLDELAY */ | RAW | LCASE | CBREAK /* | TANDEM */);
  370.         (void) stty(0, &sgt);
  371. #ifdef TIOCREMOTE
  372.         {
  373.             int    on = 1;
  374.  
  375.             (void) ioctl(0, TIOCREMOTE, (UnivPtr) &on);
  376.         }
  377. #endif /* TIOCREMOTE */
  378.         i = getpid();
  379.         (void) ioctl(0, TIOCSPGRP, (UnivPtr) &i);
  380.         (void) setpgrp(0, i);
  381.         execv(argv[0], (const char **) &argv[1]);
  382.         raw_scream("execve failed! %s\n");
  383.         _exit(errno + 1);
  384.     }
  385.  
  386.     newp = (Process *) emalloc(sizeof *newp);
  387.  
  388. #ifdef    O_NDELAY
  389.     fcntl (ptyfd, F_SETFL, O_NDELAY);
  390. #endif
  391.     newp->p_fd = ptyfd;
  392.     newp->p_pid = pid;
  393.  
  394.     newbuf = do_select((Window *)NULL, bufname);
  395.     newbuf->b_type = B_PROCESS;
  396.     newp->p_buffer = newbuf;
  397.     newbuf->b_process = newp;    /* sorta circular, eh? */
  398.     pop_wind(bufname, clobber, B_PROCESS);
  399.     /* Pop_wind() after everything is set up; important!
  400.        Bindings won't work right unless newbuf->b_process is already
  401.        set up BEFORE NEWBUF is first SetBuf()'d. */
  402.     ToLast();
  403.     if (!bolp())
  404.         LineInsert(1);
  405.  
  406.     cmdbuf[0] = '\0';
  407.     va_init(ap, clobber);
  408.     while ((cp = va_arg(ap, char *)) != NULL) {
  409.         size_t    pl = strlen(cmdbuf);
  410.  
  411.         swritef(&cmdbuf[pl], sizeof(cmdbuf)-pl, "%s ", cp);
  412.     }
  413.     va_end(ap);
  414.  
  415.     newp->p_name = copystr(cmdbuf);
  416.     newp->p_state = NEW;
  417.     newp->p_reason = 0;